﻿using System;
using System.IO;
using System.Text;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using MongoDB.Driver.GridFS;

namespace ZilLion.Core.MongoDbManager.GridFs
{
    public class GridFsRepository : MongoDbRepository, IGridFsRepository, IDisposable
    {
        public GridFsRepository() : this(new DefaultMongoDbContext())
        {
        }

        public GridFsRepository(IMongoDbContext context) : base(context)
        {
            InitGridFs();
        }

        public void Dispose()
        {
            MongoServer.Disconnect();
        }

        /// <summary>
        ///     RootName
        /// </summary>
        public string RootName { get; set; }

        /// <summary>
        ///     GridFS
        /// </summary>
        public MongoGridFS MongoGridFs { get; set; }

        /// <summary>
        ///     Server
        /// </summary>
        public MongoServer MongoServer { get; set; }


        ~GridFsRepository()
        {
            Dispose();
        }

        public void InitGridFs()
        {
            if (Context != null)
            {
                MongoServerSettings settings = null;
                MongoServerAddress mongoServerAddress;
                if (MongoServerAddress.TryParse(Context.ServerConnectString, out mongoServerAddress))
                    settings = new MongoServerSettings
                    {
                        Server = mongoServerAddress,
                        MaxConnectionPoolSize = 500, //最大连接池数量
                        WaitQueueSize = 10 //等待列队数量
                    };
                if (settings != null)
                {
                    MongoServer = new MongoServer(settings);
                    var gridFsSettings = new MongoGridFSSettings {Root = Context.RootName};
                    MongoGridFs = new MongoGridFS(MongoServer, Context.DatabaseName, gridFsSettings);
                }
            }
        }

        #region 操作文件

        public string UploadFile(string filePath)
        {
            using (var fs = new FileStream(filePath, FileMode.Open))
            {
                var gridFsInfo = MongoGridFs.Upload(fs, new FileInfo(filePath).Name);
                var fileId = gridFsInfo.Id;
                return fileId.ToString();
            }
        }

        public string UploadFile(Stream fileStream, string fileName)
        {
            var gridFsInfo = MongoGridFs.Upload(fileStream, fileName);
            var fileId = gridFsInfo.Id;
            return fileId.ToString();
        }

        public string UploadFile(byte[] bytes, string fileName)
        {
            var gridFsInfo = MongoGridFs.Upload(new MemoryStream(bytes), fileName);
            var fileId = gridFsInfo.Id;
            return fileId.ToString();
        }

        public void DeleteFileById(string key)
        {
            var oid = new ObjectId(key);
            var file = MongoGridFs.FindOne(Query.EQ("_id", oid));
            MongoGridFs.Delete(file.Name);
        }

        /// <summary>
        ///     删除报表结果
        /// </summary>
        /// <param name="fileName"></param>
        public void DeleteFileByFileName(string fileName)
        {
            MongoGridFs.Delete(fileName);
        }

        #endregion

        #region 获取文件

        public byte[] GetFileAsBytesByKey(string key)
        {
            try
            {
                var oid = new ObjectId(key);
                var file = MongoGridFs.FindOne(Query.EQ("_id", oid));

                using (var stream = file.OpenRead())
                {
                    return stream.ToByteArray();
                }
            }
            catch (Exception)
            {
                return null;
            }
        }

        public Stream GetFileAsStreamByKey(string key)
        {
            try
            {
                var oid = new ObjectId(key);

                var file = MongoGridFs.FindOne(Query.EQ("_id", oid));
                return file.OpenRead();
            }
            catch (Exception)
            {
                return null;
            }
        }

        public byte[] GetFileAsBytesByFileName(string fileName)
        {
            try
            {
                var file = MongoGridFs.FindOne(fileName);

                using (var stream = file.OpenRead())
                {
                    return stream.ToByteArray();
                }
            }
            catch (Exception)
            {
                return null;
            }
        }

        public Stream GetFileAsStreamByFileName(string fileName)
        {
            try
            {
                var file = MongoGridFs.FindOne(fileName);
                return file.OpenRead();
            }
            catch (Exception)
            {
                return null;
            }
        }

        public bool TryDownloadFileByKey(string id, string targetPath)
        {
            try
            {
                var oid = new ObjectId(id);

                var file = MongoGridFs.FindOne(Query.EQ("_id", oid));


                using (var stream = file.OpenRead())
                {
                    var bytes = new byte[stream.Length];
                    stream.Read(bytes, 0, (int) stream.Length);
                    using (var newFs = new FileStream(targetPath, FileMode.Create))
                    {
                        newFs.Write(bytes, 0, bytes.Length);
                    }
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public bool TryDownloadFileByFileName(string fileName, string targetPath)
        {
            try
            {
                var file = MongoGridFs.FindOne(fileName);


                using (var stream = file.OpenRead())
                {
                    var bytes = new byte[stream.Length];
                    stream.Read(bytes, 0, (int) stream.Length);
                    using (var newFs = new FileStream(targetPath, FileMode.Create))
                    {
                        newFs.Write(bytes, 0, bytes.Length);
                    }
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        ///     获取文件为string
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public string GetFileAsStringByFileName(string filename)
        {
            string tablestr;


            using (var gfs = MongoGridFs.FindOne(filename).OpenRead())
            {
                using (TextReader reader = new StreamReader(gfs, Encoding.UTF8))
                {
                    tablestr = reader.ReadToEnd();
                }
            }
            return tablestr;
        }

        public string GetFileAsStringByKey(string key)
        {
            string tablestr;
            var oid = new ObjectId(key);


            using (var gfs = MongoGridFs.FindOne(Query.EQ("_id", oid)).OpenRead())
            {
                using (TextReader reader = new StreamReader(gfs, Encoding.UTF8))
                {
                    tablestr = reader.ReadToEnd();
                }
            }
            return tablestr;
        }

        #endregion
    }
}